`timescale 1ns/1ns

module spi_tb;

parameter SYSCLK_PERIOD = 10;

reg SYSCLK;
reg NSYSRESET;

initial
begin
    SYSCLK = 1'b0;
    NSYSRESET = 1'b0;
end

/*iverilog */
initial
begin            
    $dumpfile("wave.vcd");        //生成的vcd文件名称
    $dumpvars(0, spi_tb);    //tb模块名称
end
/*iverilog */

input spi_miso;
output spi_clk;
output spi_mosi;
reg miso;
reg [7:0] indata;
assign spi_miso = (spi_u0.spi_state == spi_u0.spi_rw) ? miso : 1'b0;
always @(*)begin
    case(spi_u0.spi_cnt)
    4'd0: miso = indata[7];
    4'd1: miso = indata[6];
    4'd2: miso = indata[5];
    4'd3: miso = indata[4];
    4'd4: miso = indata[3];
    4'd5: miso = indata[2];
    4'd6: miso = indata[1];
    4'd7: miso = indata[0];
    4'd8: miso = 1'b0;
    default: miso = 1'b0;
    endcase
end
reg [31:0] addr;

reg [31:0] mem_wdata;
reg [3:0] mem_wstrb;
wire [31:0] mem_rdata;
wire mem_ready;
reg mem_valid;
initial
begin
    #(SYSCLK_PERIOD * 10 )
        NSYSRESET = 1'b1;
    #1000
        $stop;
end

always @(SYSCLK)
    #(SYSCLK_PERIOD / 2.0) SYSCLK <= !SYSCLK;

reg [3:0] cnt;
always@(posedge SYSCLK or negedge NSYSRESET)begin
    if(!NSYSRESET)begin
        cnt <= 4'h0;
        addr <= 32'h0;
        mem_valid <= 1'b0;
        mem_wdata <= 32'h0;
        mem_wstrb <= 4'd0;
        indata <= 8'ha1;
    end
    else if(cnt!=4'hf) begin
        case(cnt)
        4'd0:begin
            mem_wdata <= 32'h2;
            mem_wstrb <= 4'h1;
            mem_valid <= 1'b1;
            addr <= 32'h1000_0008;
            cnt <= 4'd0;
            if(mem_ready)begin
                mem_valid <= 1'b0;
                addr <= 32'h1000_0004;
                mem_wstrb <= 4'hf;
                mem_wdata <= 32'h55;
                cnt <= 4'd1;
            end
        end
        4'd1:begin
            cnt <= 4'd2;
            addr <= 32'h1000_0004;            
        end
        4'd2:begin
            mem_wstrb <= 4'hf;
            mem_valid <= 1'b1;
            mem_wdata <= 32'ha5;
            addr <= 32'h1000_0004;
            cnt <= 4'd2;
            if(mem_ready)begin
                mem_valid <= 1'b0;
                mem_wstrb <= 4'd0;
                mem_wdata <= mem_rdata + 1'b1;
                cnt <= 4'd3;
            end
        end
        4'd3:begin
            cnt <= 4'd3;
            mem_wstrb <= 4'h0;
            mem_valid <= 1'b1;
            mem_wdata <= 32'ha5;
            addr <= 32'h1000_0004;
            if(mem_ready)begin
                mem_valid <= 1'b0;
                mem_wstrb <= 4'd0;
                cnt <= 4'd4;
            end
        end
        4'd4:begin
            cnt <= 4'd3;
        end
        endcase
    end
end
spi spi_u0(
    .clk(SYSCLK),
    .resetn(NSYSRESET),

    .mem_valid(mem_valid),
    .mem_rdata(mem_rdata),
    .mem_wdata(mem_wdata),
    .mem_ready(mem_ready),
    .mem_wstrb(mem_wstrb),
    .mem_addr(addr),

    .spi_clk(spi_clk),
    .spi_mosi(spi_mosi),
    .spi_miso(spi_miso)
);

endmodule